#pragma once

#include "ShmMessagePool.hpp"
#include "ShmMessageNodeLockQueue.hpp"
#include "LOG_CYC.hpp"

/*
    管理共享内存消息的分配和管理
    多线程/多进程安全
*/
class ShmMessageManager {
public:
    // 构造函数，初始化节点池和带锁的队列
    ShmMessageManager()
        : _pool()
        , _lockQueue(MAX_SHM_MESSAGE_CONNECTIONS) {
        LOG_CYC(NORMAL, "ShmMessageManager 初始化", nullptr);
    }

    // 执行申请一块共享内存消息
    ShmMemoryBlock AllocateMessage(size_t size) {
        ShmMessageNode* node = _pool.New(); // 从节点池中获取一个新的节点

        node->SetFunctionType(ShmFunctionType::AllocateSharedMemory); // 执行申请功能
        node->SetSize(size); // 设置节点的大小
        node->SetShmMemoryBlock(-1, -1, -1);

        // 阻塞执行
        return BlockingFetchData(node);
    }

    // 释放共享内存消息
    void DeallocateMessage(ShmMemoryBlock& block) {
        ShmMessageNode* node = _pool.New(); // 从节点池中获取一个新的节点
        node->SetFunctionType(ShmFunctionType::ReleaseSharedMemory);    // 执行释放功能
        node->SetShmMemoryBlock(block._shmID, block._shmPos, block._blockSize);

        LOG_CYC(NORMAL, "设置释放内存块信息，FileId：%d，Pos：%d", block._shmID, block._shmPos);

        _lockQueue.push(node, _pool); // 将节点推入带锁的队列
    }

    // 数据结构消息
    ShmMemoryBlock GetDataMessage(DataStructureBlock& block) {
        ShmMessageNode* node = _pool.New(); // 从节点池中获取一个新的节点

        node->SetFunctionType(ShmFunctionType::DataStructure); // 执行数据结构功能
        node->SetDataStructureBlock(block._dataStructureType, block._functionType, block.buffer);  // 设置执行的数据结构函数
        node->SetShmMemoryBlock(-1, -1, -1);    // 初始化返回节点

        // 阻塞执行
        return BlockingFetchData(node);
    }

    // void SetDataMessage(int DataStructurType, int FuncType, const std::string name, ShmSharedPtrNode* node) {

    // }

    // 获取一个队列中的消息节点
    // 返回值：ShmMessageNode*，指向从队列中取出的消息节点的指针
    ShmMessageNode* GetMessageNodeFromQueue() {
        LOG_CYC(_DEBUG, "当前队列大小：%d", _lockQueue.size());

        ShmMessageNode* node = _lockQueue.front(_pool); // 获取队列中的头节点
        _lockQueue.pop(_pool); // 弹出队列中的头节点

        return node;
    }

    ShmMessagePool& GetMessagePool() { return _pool; }

private:

    // 阻塞执行返回数据
    ShmMemoryBlock BlockingFetchData(ShmMessageNode*& node) {
        // 在子进程进入等待之前，不允许主进程执行申请操作
        ShmScopedLock lock(node->GetMutex());

        // 将节点推入带锁的队列
        _lockQueue.push(node, _pool);

        // 等待主进程执行
        node->Wait();
        assert(node->isExecuteSuccessful());
        ShmMemoryBlock retBlock = node->GetShmMemoryBlock();

        _pool.Delete(node);

        return retBlock;
    }

    // 阻塞执行
    void BlockingExecute(ShmMessageNode*& node) {
        // 在子进程进入等待之前，不允许主进程执行申请操作
        ShmScopedLock lock(node->GetMutex());

        // 将节点推入带锁的队列
        _lockQueue.push(node, _pool);

        // 等待主进程执行
        node->Wait();
        assert(node->isExecuteSuccessful());

        _pool.Delete(node);

    }

private:
    ShmMessageNodeLockQueue _lockQueue; // 带锁的队列，用于管理节点的排队和同步访问
    ShmMessagePool _pool;               // 节点池，用于管理共享内存消息的分配和释放
};
